package com.feinno.urcs.group.http.servlet;

import com.feinno.urcs.auth.token.HttpTokenAuthorizationService;
import com.feinno.urcs.group.api.GroupInfoVersionCacheManager;
import com.feinno.urcs.group.api.GroupListVersionCacheManager;
import com.feinno.urcs.group.api.GroupService;
import com.feinno.urcs.group.http.util.HttpHelper;
import com.feinno.urcs.group.http.util.XcapParser;
import com.feinno.urcs.group.interop.FxDataValidateService;
import com.feinno.urcs.nai.IMPU;
import org.helium.framework.annotations.FieldSetter;
import org.helium.framework.annotations.ServiceSetter;
import org.helium.framework.annotations.ServletImplementation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by wuzhiguo on 15-5-11.
 */
// @ServletImplementation(id = "group:GroupHttpServlet")
public class GroupHttpServlet extends BaseHttpServlet {
	private static final Logger LOGGER = LoggerFactory.getLogger(GroupHttpServlet.class);

	@FieldSetter("${checkAuthorizationEnable}")
	private boolean checkAuthorizationEnable;
	@ServiceSetter
	private GroupService groupService;
	@ServiceSetter
	private GroupListVersionCacheManager groupListVersionCacheManager;
	@ServiceSetter
	private GroupInfoVersionCacheManager groupInfoVersionCacheManager;
	@ServiceSetter(id = "urcs:HttpTokenAuthorizationService")
	private HttpTokenAuthorizationService httpTokenAuthorizationService;
	@ServiceSetter
	private FxDataValidateService fxDataValidateService;
	@Override
	protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doWork(request, response);
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doWork(request, response);
	}

	@Override
	protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doWork(request, response);
	}

	private void doWork(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
		String bodyString = "";
		try {
			byte[] body = HttpHelper.getRequestBody(request);
			bodyString = new String(body, "utf-8");
			if (LOGGER.isInfoEnabled()) {
				String requestString = HttpHelper.getRequestString(request, bodyString);
				LOGGER.info(String.format("Received Request: %s", requestString));
			}

			XcapParser parser = new XcapParser();
			parser.parse(request.getRequestURI());
			if (LOGGER.isInfoEnabled()) {
				LOGGER.info(String.format("Parse XcapParser: %s", parser));
			}

			IMPU senderIMPU = parseSenderIMPU(request);
			IMPU xuiIMPU = parseXuiIMPU(request, parser);
			IMPU targetIMPU = parseTargetIMPU(request, parser);

			if (senderIMPU == null) {
				String requestString = HttpHelper.getRequestString(request, bodyString);
				LOGGER.error(String.format("parseSenderIMPU Failed. Received Request: %s", requestString));
				response.sendError(400, "ArgsError");
				return;
			}

			if (xuiIMPU == null) {
				String requestString = HttpHelper.getRequestString(request, bodyString);
				LOGGER.error(String.format("parseXuiIMPU Failed. Received Request: %s", requestString));
				response.sendError(400, "ArgsError");
				return;
			}

			final GroupHttpContext ctx = new GroupHttpContext(
					groupService,
					request,
					response,
					parser,
					bodyString,
					senderIMPU,
					xuiIMPU,
					targetIMPU,
					groupListVersionCacheManager,
					groupInfoVersionCacheManager);
			ctx.setFxDataValidateService(fxDataValidateService);
			if (checkAuthorizationEnable) {
				checkAuthorization(ctx, httpTokenAuthorizationService, (int status, String reason) -> {
							try {
								if (status == 200) {
									if (LOGGER.isInfoEnabled()) {
										String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
										LOGGER.info(String.format("checkAuthorization Successfully. Received Request: %s", requestString));
									}

									doBusiness(ctx);

								} else {
									String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
									LOGGER.error(String.format("checkAuthorization Failed. status: %s reason: %s Received Request: %s", status, reason, requestString));
									response.sendError(status, reason);
								}

							} catch (Exception ex) {
								String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
								LOGGER.error(String.format("checkAuthorization Callback Error. Received Request: %s", requestString), ex);
							}
						}
				);

				return;
			}

			doBusiness(ctx);

		} catch (Exception ex) {
			String requestString = HttpHelper.getRequestString(request, bodyString);
			LOGGER.error(String.format("doWork() Error. Received Request: %s", requestString), ex);
			response.sendError(500, "ServerError");
		}
	}

	private void doBusiness(final GroupHttpContext ctx) throws IOException {
		try {
			BaseHttpServlet handler = GroupHttpDispatcher.dispatch(ctx.getRequest().getMethod(), ctx.getParser());
			if (handler == null) {
				String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
				LOGGER.error(String.format("dispatch handler return null. Received Request: %s", requestString));
				ctx.getResponse().sendError(400, "ArgsError");
				return;
			}

			handler.process(ctx);

		} catch (Exception ex) {
			String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
			LOGGER.error(String.format("doBusiness() Error. Received Request: %s", requestString), ex);
			ctx.getResponse().sendError(500, "ServerError");
		}
	}
}
